package nckd.wnqjt.tmc.tda.plugin.form;

import com.alibaba.fastjson.JSON;
import kd.bos.ai.util.JsonUtil;
import kd.bos.algo.DataSet;
import kd.bos.algo.Row;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.db.DB;
import kd.bos.db.DBRoute;
import kd.bos.db.tx.TX;
import kd.bos.db.tx.TXHandle;
import kd.bos.entity.AppInfo;
import kd.bos.entity.AppMetadataCache;
import kd.bos.entity.qing.*;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.exception.BosErrorCode;
import kd.bos.exception.KDException;
import kd.bos.form.IFormView;
import kd.bos.form.IPageCache;
import kd.bos.form.ShowType;
import kd.bos.form.control.IQingAnalysis;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.list.ListShowParameter;
import kd.bos.mvc.SessionManager;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.report.ReportShowParameter;
import kd.bos.servicehelper.QueryServiceHelper;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhujintao
 * @date 2024/11/05
 * @desc  低效账户单位分布
 */
public class InefficientAccountQingDataProvider extends AbstractFormPlugin implements IQingDataProvider {
    /**
     * 获取表头信息定义
     */
    @Override
    public QingMeta getMeta(String pageId) {
        String entityKey = "cas_bankjournal";//银行日记账
        QingMeta meta = new QingMeta();
        EntryEntity entity = new EntryEntity();
        entity.setKey(entityKey); //实体名(唯一标识)	是
        entity.setName(new LocaleString("低效账户查询")); //实体别名	是
        entity.setPkFieldName("id");//主键名称	是
        meta.addEntryEntity(entity);

        Field column = new Field();
        column.setEntity(entityKey);//字段所属实体key	否
        column.setKey("id");// 字段名(唯一标识)	是
        column.setFieldType(QingFieldType.Int.toNumber()); //数据类型	是
        column.setName(new LocaleString("id")); //字段别名	是
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);//字段所属实体key	否
        column.setKey("orgname");// 字段名(唯一标识)	是
        column.setFieldType(QingFieldType.String.toNumber()); //数据类型	是
        column.setName(new LocaleString("使用组织")); //字段别名	是
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);
        column.setKey("counttranrecord");
        column.setFieldType(QingFieldType.Int.toNumber());
        column.setName(new LocaleString("低效账号交易笔数"));
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);
        column.setKey("countaccount");
        column.setFieldType(QingFieldType.Int.toNumber());
        column.setName(new LocaleString("低效账户数"));
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);
        column.setKey("bizdate");
        column.setFieldType(QingFieldType.DateTime.toNumber());
        column.setName(new LocaleString("业务日期"));
        meta.addColumn(column);
        return meta;
    }

    /**
     * 获取轻分析数据
     *
     * @param startRow 起始行
     * @param limit    每页的数据量
     * @return 轻分析数据
     */
    @Override
    public QingData getData(String pageId, int startRow, int limit) {
        //拿过滤条件，进行取数
        String qFilter = getPageCache().get("qFilter");
        if (qFilter != null) {
            //通过此方法拿到过滤参数
            Map<String, Object> filterParam = (Map) JSON.parseObject(qFilter, Map.class);
        }
        //先获取到低效账户设置的参数
        Map<String, Object> settingFilterMap = dormantSettingFilter();
        //先获取符合条件的账户列表
        QFilter acctimefilter = new QFilter("opendate", QCP.less_equals, settingFilterMap.get("queryStartDate"));
        QFilter finorgtypefilter = new QFilter("finorgtype", QCP.not_equals, "FI-015");
        QFilter acctstatusfilter = new QFilter("acctstatus", QCP.not_equals, "closed");
        QFilter[] acctfilters = new QFilter[]{acctimefilter, finorgtypefilter, acctstatusfilter};
        String getAcctSelectedFieds = "id,company,openorg,issetbankinterface,bank,bankaccountnumber,name,currencyname,defaultcurrency,opendate,acctstatus,acctstyle,accttype,acctproperty,manager,acctname,finorgtype";
        DataSet acctDataSet = QueryServiceHelper.queryDataSet("dormantAcct", "bd_accountbanks", getAcctSelectedFieds, acctfilters, null);
        List<String> accountNoList = new ArrayList<>();
        while (acctDataSet.hasNext()) {
            Row next = acctDataSet.next();
            String bankaccountnumber = next.getString("bankaccountnumber");
            accountNoList.add(bankaccountnumber);
        }
        //银行日记账
        QFilter accountFilter = new QFilter("accountbank.bankaccountnumber", QCP.in, accountNoList);
        String getDailySelectedFieds = "id,org.id orgid,org.number orgnumber,org.name orgname,accountbank.bankaccountnumber bankaccountnumber,bizdate";
        QFilter dailytimefilter = (new QFilter("bizdate", ">=", settingFilterMap.get("queryStartDate"))).and(new QFilter("bizdate", "<=", settingFilterMap.get("queryEndDate")));
        QFilter[] bankjournalfilters = new QFilter[]{accountFilter, dailytimefilter};
        DataSet bankJournalAllDataSet = QueryServiceHelper.queryDataSet("dormantAcct", "cas_bankjournal", getDailySelectedFieds, bankjournalfilters, null);
        //拿到明细 获取低于设置的账户
        //获取到的明细数据先根据账户分组 得到账户的低效数
        HashMap<String, Object> count = new HashMap();
        count.put("tradenumber", settingFilterMap.get("tradenumber"));
        DataSet accountcountDataSet = bankJournalAllDataSet.copy().groupBy(new String[]{"orgid", "bankaccountnumber"}).count("counttradecount").finish();
        //符合条件的账户
        accountcountDataSet = accountcountDataSet.filter("counttradecount < tradenumber", count);
        //再统计每个组织有多少个账户
        DataSet orgcountDataSet = accountcountDataSet.copy().groupBy(new String[]{"orgid"}).count("countaccount").finish();
        DataSet result = accountcountDataSet.leftJoin(orgcountDataSet).on("orgid", "orgid").select(accountcountDataSet.getRowMeta().getFieldNames(), new String[]{"countaccount"}).finish();
        //每个组织有多少个账户的结果  再关联明细
        DataSet finish = result.leftJoin(bankJournalAllDataSet).on("bankaccountnumber", "bankaccountnumber").select(new String[]{"counttradecount", "countaccount"}, bankJournalAllDataSet.getRowMeta().getFieldNames()).finish();
        QingData data = null;
        if (startRow < 200) {
            data = new QingData();
            Map<String, Integer> dataindex = new HashMap<String, Integer>();
            dataindex.put("id", 0);
            dataindex.put("orgname", 1);
            dataindex.put("counttranrecord", 2);
            dataindex.put("countaccount", 3);
            dataindex.put("bizdate", 4);
            data.setDataindex(dataindex);

            List<Object[]> rows = new ArrayList<Object[]>();
            while (finish.hasNext()) {
                Row row = finish.next();
                Object[] obj = new Object[5];
                obj[0] = row.getLong("id");
                obj[1] = row.getString("orgname");
                obj[2] = row.getInteger("counttradecount");
                obj[3] = row.getInteger("countaccount");
                Timestamp timestamp = (Timestamp) row.get("bizdate");
                long time = timestamp.getTime();
                obj[4] = time;
                rows.add(obj);
            }
            data.setRows(rows);
        }
        return data;
    }

    /**
     * 获取银行低效账户设置 copy自 kd.tmc.am.report.bankacct.helper.DormantSettingFilterHelper#dormantSettingFilter()
     *
     * @return
     */
    public static Map<String, Object> dormantSettingFilter() {
        HashMap<String, Object> settingFilterMap = new HashMap();
        int tradenumber = 5;
        String datarange = "sixmonth";
        TXHandle txHandle = TX.requiresNew();
        Throwable var4 = null;

        try {
            String selectStr = "SELECT FTRADECOUNT,FDATARANGE FROM T_AM_DORMANTSET";
            Map<String, String> info = (Map) DB.query(new DBRoute("sys"), selectStr, new Object[0], (rs) -> {
                Map<String, String> lockInfo = new HashMap();
                if (rs.next()) {
                    lockInfo.put("FTRADECOUNT_MAP", rs.getString(1));
                    lockInfo.put("FDATARANGE_MAP", rs.getString(2));
                }

                return lockInfo;
            });
            if (info.size() != 0) {
                tradenumber = Integer.parseInt((String) info.get("FTRADECOUNT_MAP"));
                datarange = (String) info.get("FDATARANGE_MAP");
            }
        } catch (Throwable var14) {
            var4 = var14;
            throw var14;
        } finally {
            if (txHandle != null) {
                if (var4 != null) {
                    try {
                        txHandle.close();
                    } catch (Throwable var13) {
                        var4.addSuppressed(var13);
                    }
                } else {
                    txHandle.close();
                }
            }

        }

        Date queryStartDate = new Date();
        Date queryEndDate = new Date();
        if (datarange.contains("custom")) {
            String[] data = datarange.split("&");
            if (data.length == 3) {
                queryStartDate = new Date(Long.parseLong(data[1]));
                queryEndDate = new Date(Long.parseLong(data[2]));
            }
        } else {
            queryStartDate = transRange2Date(datarange);
            queryEndDate = getNextDay(getCurrentDate(), 1);
        }

        settingFilterMap.put("queryStartDate", queryStartDate);
        settingFilterMap.put("queryEndDate", queryEndDate);
        settingFilterMap.put("tradenumber", tradenumber);
        return settingFilterMap;
    }

    public static Date transRange2Date(String datarange) {
        Date endDate = getNextDay(getCurrentDate(), 1);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if ("onemonth".equals(datarange)) {
            calendar.add(2, -1);
        } else if ("threemonth".equals(datarange)) {
            calendar.add(2, -3);
        } else if ("sixmonth".equals(datarange)) {
            calendar.add(2, -6);
        } else if ("nightmonth".equals(datarange)) {
            calendar.add(2, -9);
        } else if ("oneyear".equals(datarange)) {
            calendar.add(1, -1);
        } else if ("twoyear".equals(datarange)) {
            calendar.add(1, -2);
        } else if ("threeyear".equals(datarange)) {
            calendar.add(1, -3);
        }

        Date beginDate = getDataFormat(calendar.getTime(), true);
        return beginDate;
    }

    public static Date getDataFormat(Date date, boolean isStart) {
        String dateStr = (new SimpleDateFormat("yyyy-MM-dd")).format(date);
        String suffix = " 00:00:00";
        if (!isStart) {
            suffix = " 23:59:59";
        }

        try {
            return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(dateStr + suffix);
        } catch (ParseException var5) {
            throw new KDException(var5, BosErrorCode.systemError, new Object[0]);
        }
    }

    public static Date getNextDay(Date date, int i) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(5, cal.get(5) + i);
        return cal.getTime();
    }

    public static Date getCurrentDate() {
        Calendar cal = new GregorianCalendar();
        cal.set(11, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(14, 0);
        return cal.getTime();
    }

    @Override
    public void setFilterParameter(String filterParameter) {
        IPageCache pageCache = getPageCache();
        pageCache.put("qFilter", filterParameter);

    }

    @Override
    public String getFilterParameter() {
        return getPageCache().get("qFilter");
    }

    /**
     * 获取动态表单联查信息
     *
     * @param pageId
     * @param ctrKey
     * @return
     */
    @Override
    public List<QingLinkageInfo> getLinkageInfo(String pageId, String ctrKey) {
        //return IQingDataProvider.super.getLinkageInfo(pageId, ctrKey);
        List<QingLinkageInfo> infos = new ArrayList<QingLinkageInfo>();
        QingLinkageInfo info = new QingLinkageInfo();
        Map<String, String> formKey = new HashMap<>();
        AppInfo appInfo = AppMetadataCache.getAppInfo("cas");
        //String appId = this.getView().getFormShowParameter().getAppId();
        formKey.put("AppId", appInfo.getAppId()); //需要打开的表单所在应用的id
        //String formId = this.getView().getFormShowParameter().getFormId();
        formKey.put("FormId", "nckd_inefficientacctrpt"); //需要打开的表单的id
        formKey.put("System", "IERP");
        formKey.put("CtrKey", ctrKey);
        info.setFormKey(JsonUtil.encodeToString(formKey));
        info.setFormDisplayName("低效账户明细报表");//联查到表单的显示名称
        info.setFormPrimaryKey("id");//联查到表单的主键
        infos.add(info);//可以添加多个QingLinkageInfo对象
        this.getView().getPageCache().put("qingViewControlKey", ctrKey);//必要语句!
        return infos;
    }

    /**
     * <p>调用此接口，触发业务逻辑，具体业务联查实现此接口<p/>
     *
     * @param ids    轻分析得到动态表单需要联査的1d的集合
     * @param pageId
     * @param formId
     * @param appId
     */
    @Override
    public void fireLinkageInfo(List<String> ids, String pageId, String formId, String appId) {
        //IQingDataProvider.super.fireLinkageInfo(ids, pageId, formId, appId);
        /*具体的表单打开逻辑，业务自己去实现
        ids:联查到的主键的值
        pageId:触发联査的页面的pageId，可用于找到触发联査的页面: FormView view = (FormView)Sessiomanager.getCurrent().getView(pageId)
        formId:联查到的表单的id
        appId:联查到的表单所在应用的Id
        */

        /*注意: 如果需要使用芒穹的view.showForm 方式打开表单，需要添加以下代码*/
        // 组装 FormShomParaneter(披照业务场景亲实现)
        ReportShowParameter reportShowParameter = new ReportShowParameter();
        reportShowParameter.getOpenStyle().setShowType(ShowType.Modal);
        reportShowParameter.setAppId(appId);
        reportShowParameter.setFormId(formId);//报表标识
        //拿过滤条件，进行取数
        String qFilter = getPageCache().get("qFilter"); //从仪表板进去 拿不到
        //通过此方法拿到过滤参数
        Map<String, Object> filterParam = new HashMap<>();
        // 设置报表过滤条件
        ReportQueryParam reportQueryParam = new ReportQueryParam();
        //FilterInfo filterInfo = new FilterInfo();
        //filterInfo.addFilterItem("nckd_orgview", filterParam.get("nckd_orgview"));
        //filterInfo.addFilterItem("nckd_org", filterParam.get("nckd_org"));
        //filterInfo.addFilterItem("nckd_currency", filterParam.get("nckd_currency"));
        //filterInfo.addFilterItem("bizdate", filterParam.get("nckd_querydate"));
        //filterInfo.addFilterItem("nckd_amountunit", filterParam.get("nckd_amountunit"));
        filterParam.put("id", ids);
        //reportQueryParam.setFilter(filterInfo);
        reportQueryParam.setCustomParam(filterParam);
        reportShowParameter.setQueryParam(reportQueryParam);

        /*******************************showForm必要的代码******************************************/
        IFormView view = SessionManager.getCurrent().getView(pageId);
        String ctrKey = this.getView().getPageCache().get("qingViewControlKey");
        if (ctrKey != null) {
            if (view.getControl(ctrKey) instanceof IQingAnalysis) {
                //设计器的场景，直接showForm
                view.showForm(reportShowParameter);
                return;
            }
        }
        //其他场景需要，返回FormShowParameter，由轻分析来 showForm
        this.getView().setClientReturnData(ListShowParameter.toJsonString(reportShowParameter));
        /*******************************showForm必要的代码******************************************/
    }
}